/* 
	Written by Robert Nyman, http://www.robertnyman.com
	Inspired by http://www.insideria.com/2008/03/air-api-performing-updates-in-1.html, and then modified
*/	
var AIRUpdater = function () {
	// This is only used for the filename of the installer
	var applicationName = "gdocsuploader.air";
	var applicationVersion = 0;
	var latestVersion = 0;
	/*
		URL to go to to check the value of the <version> and <releasenotes>
		The value in version is compared to the one in the applications XML setup file,
		and an update dialog is triggered if the <version> in the below XML file is higher
		From there on, suggested alternatives for the end user is to 
		start an update or cancel it for the moment
		
		Suggested XML structure:
		
		<?xml version="1.0" encoding="UTF-8"?>
		<application>
			<latestversion>0.7</latestversion>
			<releasenotes>Added automatic update downloading feature.</releasenotes>
		</application>
	*/
	var latestVersionCheckUrl = "http://gdocsuploader.googlecode.com/svn/branches/adobeair/version.xml";
	var updateAvailable = null;
	var updateAvailableDialog = null;
	var releaseNotes = null;
	var releaseNotesText = "";
	/*
		Change this URL to the download URL of your AIR app. Version number 
		and ".air" extension will automatically be added; version taken 
		from the XML value found in the latestVersionCheckUrl page
	*/	
	var updateUrl = null;
	var stream = null;
	var updateFile = null;
	
	var getApplicationVersion = function () {
		// This will get the version of the currently installed application
		var appXML = air.NativeApplication.nativeApplication.applicationDescriptor;
		var xmlObject = new DOMParser().parseFromString(appXML, "text/xml");
		applicationVersion = xmlObject.getElementsByTagName('version')[0].firstChild.nodeValue;
        air.trace("detected application version", applicationVersion);
	};
	
	var getLatestVersion = function () {
		/* 
			Checks for what the latest available version is 
			from the URL specified in latestVersionCheckUrl
		*/	
		var XMLHttp = new XMLHttpRequest();
		XMLHttp.onreadystatechange = function () {
			if (XMLHttp.readyState === 4) {
                parser=new DOMParser();
				var response = parser.parseFromString(XMLHttp.responseText, "text/xml");
				var releaseNotesNode = response.getElementsByTagName("releasenotes")[0];
                air.trace("Release notes:", releaseNotesNode);
				/*
					Adds a reference to a releaseNote for the latest version, 
					IF a <releasenotes> node exists
				*/
				if (typeof releaseNotesNode === "object" && releaseNotesNode.firstChild) {
					releaseNotesText = releaseNotesNode.firstChild.nodeValue;
				}

                var urlNode = response.getElementsByTagName("url")[0];
                air.trace(urlNode);
                if (typeof urlNode === "object" && urlNode.firstChild) {
                    updateUrl = urlNode.firstChild.nodeValue;
                    air.trace("Update URL:", updateUrl);
                }

				var latestVersionNode = response.getElementsByTagName("latestversion")[0];
				/*
					Triggers a version comparison with the existing installed application, 
					IF a <latestversion> node exists
				*/	
				if (typeof latestVersionNode === "object" && latestVersionNode.firstChild) {
					latestVersion = latestVersionNode.firstChild.nodeValue;
                    air.trace('Latest version:', latestVersion);
					compareVersions();
				}
			}
		};
		XMLHttp.open("GET", latestVersionCheckUrl, true);
		XMLHttp.send(null);
	};
	
	var compareVersions = function () {
        air.trace("Comparing versions", applicationVersion, latestVersion);
        var herenums = new Array();
        var therenums = new Array();
        var here = applicationVersion.split('.');
        for (i = 0; i < 6; i++) {
            if (here.length > 0) {
                val = here.shift();
                herenums.push(parseInt(val));
            } else {
                herenums.push(0);
            }
        }
        var there = latestVersion.split('.');
        for (i = 0; i < 6; i++) {
            if (there.length > 0) {
                val = there.shift();
                therenums.push(parseInt(val));
            } else {
                therenums.push(0);
            }
        }
        
        upavail = false;

        if (herenums[0] > 0 && therenums > [0]) {
            for (i = 0; i < 6; i++) {
                if (therenums[i] > herenums[i]) {
                    upavail = true;
                    break;
                } else if (therenums[i] < herenums[i]) {
                    break;
                }
            }
        }

		if (upavail) {
			/*
				Here you should, for example, present an "Update available" to your
				end user, and give them the option to start the update
				The code below is just sample code:
			*/
            el = document.getElementById('updateavailable');
            el.style.display='block';
            el.onclick=initUpdateApplication;
		}
	};
	
	var initUpdateApplication = function () {
        air.trace("Updating application", updateUrl, latestVersion);
		/* 
			The updating has started. Prefereably, you'd like to hide 
			or disable the start and cancel update buttons now
		*/
		stream = new air.URLStream();
		
		/*
			This event is recommend to give the end user continuous 
			feedback about how the update goes
		*/
		stream.addEventListener(air.ProgressEvent.PROGRESS, updatingStatus);
		
		stream.addEventListener(air.Event.COMPLETE, updateApplication);
		
		// Note that the latest version number and ".air" extension is automatically added
		stream.load( new air.URLRequest(updateUrl));
	};
	
	var updatingStatus = function (e) {
		// This is example code to show updating status
		var percentage = Math.round((e.bytesLoaded / e.bytesTotal) * 100);
		document.getElementById("current-updating-status").innerHTML = percentage + "%";
	};
	
	updateApplication = function () {
        air.trace("Beginning application update");
		var ba = new air.ByteArray();
		stream.readBytes(ba, 0, stream.bytesAvailable);
		updateFile = air.File.applicationStorageDirectory.resolvePath(applicationName);
		fileStream = new air.FileStream();
		fileStream.addEventListener( air.Event.CLOSE, installUpdate );
		fileStream.openAsync(updateFile, air.FileMode.WRITE);
		fileStream.writeBytes(ba, 0, ba.length);
	 	fileStream.close();
	};
	
	var installUpdate = function () {
		var updater = new air.Updater();
		// Notice that the version name has to be present as a second parameter
		updater.update(updateFile, latestVersion);
	};
	
	return {
		init : function () {
			getApplicationVersion();
			getLatestVersion();
		}
	};
}();